home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 43 / Amiga Format CD43 (1999)(Future Publishing)(GB)(Track 1 of 2)[!][issue 1999-09].iso / -serious- / archivers / xpk / xpk_source / prefs / xpkmaster.c < prev    next >
C/C++ Source or Header  |  1999-06-14  |  42KB  |  1,532 lines

  1. #define NAME        "XpkMaster"
  2. #define DISTRIBUTION    "(Freeware) "
  3. #define REVISION    "31"
  4. #define SDI_ENDCODE
  5.  
  6. /* Programmheader
  7.  
  8.     Name:        XpkMaster
  9.     Author:        SDI
  10.     Distribution:    Freeware
  11.     Description:    Prefs program for XpkMaster
  12.     Compileropts:    -
  13.     Linkeropts:    -l amiga
  14.     ToDo:        speed up refresh, by flags based choose of to
  15.             refresh gadgets
  16.  
  17.  1.0   10.11.96 : first Version, incomplete, started to form GUI
  18.  1.1   11.11.96 : corrected, added the code a bit
  19.  1.2   16.11.96 : some more stuff
  20.  1.3   17.11.96 : completed GUI
  21.  1.4   20.11.96 : added more functions
  22.  1.5   21.11.96 : added icon creation, corrected some stuff
  23.  1.6   23.11.96 : corrected some stuff
  24.  1.7   24.11.96 : added loading and cleaned up source
  25.  1.8   30.11.96 : fixed some errors, still working incorrect
  26.  1.9   01.12.96 : and again some bugfixes
  27.  1.10  07.12.96 : correct Default dir in asl request and wb call
  28.  1.11  12.12.96 : fixed crash problem, when called by project icon with
  29.      ACTION=EDIT
  30.  1.12  13.12.96 : made the window a bit smaller for larger texts and fonts
  31.  1.13  14.12.96 : changed the Prefs include XPKM -> XPKT, XPKD -> XPKM,
  32.      other member prefixes
  33.  1.14  20.12.96 : fixed Enforcer hit (I finally have a MMU :-) and little
  34.     error
  35.  1.15  25.12.96 : corrected List handling
  36.  1.16  26.12.96 : once again changed xpkprefs.h -> now should be last time,
  37.      because I wrote the prefs support for master library
  38.  1.17  29.12.96 : fixed bug with XPKM flags
  39.  1.18  09.01.97 : changed default flags
  40.  1.19  11.01.97 : splitted master library and prefs catalog
  41.  1.20  01.03.97 : changed XpkMainPrefs structure a bit
  42.  1.21  07.03.97 : recompiled, because of structures additions
  43.  1.22  08.03.97 : fixed a crash causing typo error
  44.  1.23  02.04.97 : changed XpkTypeData structure
  45.  1.24  03.04.97 : fixed error
  46.  1.25  04.04.97 : fixed error in texts
  47.  1.26  10.04.97 : default entry now 1 and not 0
  48.  1.27  18.05.97 : corrected internal string
  49.  1.28  31.05.97 : SDI_locale changed
  50.  1.29  17.06.97 : now prints entry name for illegal entry
  51.  1.30  18.06.97 : library name file requester got wrong value
  52.  1.31  16.01.98 : now calls ClearMenuStrip
  53. */
  54.  
  55. #include <proto/exec.h>
  56. #include <proto/intuition.h>
  57. #include <proto/dos.h>
  58. #include <proto/icon.h>
  59. #include <proto/gadtools.h>
  60. #include <proto/graphics.h>
  61. #include <proto/asl.h>
  62. #include <proto/iffparse.h>
  63. #include <xpk/xpkprefs.h>
  64. #include <clib/alib_protos.h>
  65. #include <intuition/gadgetclass.h>
  66. #include <workbench/startup.h>
  67. #include <prefs/prefhdr.h>
  68. #include <exec/memory.h>
  69. #include "SDI_defines.h"
  70. #define SDI_LOCALE_NO_STRUCTS
  71. #include "SDI_locale.c"
  72. #include "SDI_ASM_STD_protos.h"
  73.  
  74. /* ------------------ defines and structures --------------------------- */
  75.  
  76. #define PARAM    "FROM,EDIT/S,USE/S,SAVE/S,PUBSCREEN/K"
  77.  
  78. #define GADGET(a)     ((struct Gadget *) a->IAddress)
  79. #define STRINF(a)    ((struct StringInfo *) (a->SpecialInfo))
  80. #define    DEFNODE(a)    ((struct PackerNode *) ((a)->ld_List.lh_Head))
  81.  
  82. #define PicSize        509    /* size of the icon */
  83.  
  84. enum {
  85. STRING_TypeName = 100,    LISTVIEW,        BUTTON_New,
  86. BUTTON_Delete,        BUTTON_Up,        BUTTON_Down,
  87. STRING_NamePatt,    STRING_FilePatt,    STRING_LibraryName,
  88. GETIMAGE,        INTEGER_Mode,        INTEGER_ChunkSize,
  89. CYCLE,            INTEGER_TimeOut,    CHECKBOX_XFD,
  90. CHECKBOX_EXT,        CHECKBOX_Password,    BUTTON_Save,
  91. BUTTON_Use,        BUTTON_Chancel
  92. };
  93.  
  94. #define PREF_VERSION    0    /* version of prefs I can work with */
  95.  
  96. #define    DEFAULT_NODE    100
  97. #define PACKER_NODE    101
  98.  
  99. #define DEF_TIMEOUT    120
  100. #define DEF_XPKM_FLAGS    (XPKM_AutoPassword | XPKM_UseExternals)
  101. #define DEF_CYCLE    2 /* XTD_ReturnError */
  102.  
  103. /* window style defines */
  104. #define SEPARATE_SAME    2
  105. #define SEPARATE_DIFF    5
  106. #define SEPARATE_BORD    5
  107.  
  108. #define TypeSIZE    49
  109. #define NamePattSIZE    49
  110. #define FilePattSIZE    99
  111.  
  112. struct PackerNode {
  113.   struct Node        pn_Node;
  114.   ULONG            pn_StdID;
  115.   UWORD            pad;    /* always StdID finished with 0 byte */
  116.   UWORD            pn_Mode;
  117.   ULONG            pn_ChunkSize;
  118.   ULONG            pn_Cycle;
  119.   UBYTE            pn_TypeName[TypeSIZE+1];
  120.   UBYTE            pn_NamePattern[NamePattSIZE+1];
  121.   UBYTE            pn_FilePattern[FilePattSIZE+1];
  122. };
  123.  
  124. struct ListData {
  125.   struct List    ld_List;
  126.   struct PackerNode    *ld_curNode;
  127.   ULONG            ld_entries;
  128.   ULONG            ld_curNumber;
  129. };
  130.  
  131. struct Args {
  132.   STRPTR from;
  133.   ULONG     edit;
  134.   ULONG     use;
  135.   ULONG  save;
  136.   STRPTR pubscreen;
  137.   ULONG     createicons;
  138. };
  139.  
  140. /* ----------------------------- Strings ------------------------------- */
  141.  
  142. #define TEXT_START_MENUMAIN    0
  143. #define NUMBER_MENUMAIN        11
  144.  
  145. enum {
  146. TEXT_WINDOW_TITLE = NUMBER_MENUMAIN,        TEXT_ENTRY_DEFAULT,
  147. TEXT_ENTRY_NEW,        TEXT_SELECT_LIBRARY,    TEXT_LOAD_PREFERENCES,
  148. TEXT_SAVE_PREFERENCES,    TEXT_TITLE_ERR_REQUEST,    TEXT_ERROR_FILEACCESS,
  149. TEXT_LIB_REQUIRED,    TEXT_VERSION_TO_HIGH,    TEXT_ERROR_FILEPROCESS,
  150. TEXT_ILLEGAL_ENTRY,    TEXT_NO_WINDOW,        GADGS_ERR_REQUEST,
  151. GADG_Save,        GADG_Use,        GADG_Cancel,
  152. GADG_Use_XFD,        GADG_Use_Externals,    GADG_AutoPassword,
  153. GADG_Timeout,        GADG_New,        GADG_Delete,
  154. GADG_Up,        GADG_Down,        GADG_Name_Pattern,
  155. GADG_File_Pattern,    GADG_Library_Name,    GADG_Mode,
  156. GADG_ChunkSize,        GADG_PackMode,        TEXT_START_SLIDER
  157. };
  158.  
  159. #define TEXT_START_OTHER    (NUMBER_MENUMAIN)
  160. #define TEXT_START_GADGET    (GADG_Save)
  161.  
  162. #define NUMBER_OTHER        (TEXT_START_GADGET-TEXT_START_OTHER)
  163. #define NUMBER_GADGET        (TEXT_START_SLIDER-TEXT_START_GADGET)
  164. #define NUMBER_SLIDER        3
  165.  
  166. struct SDI_SetLocale initloc[] = {
  167. { 400, NUMBER_MENUMAIN, TEXT_START_MENUMAIN}, /* Main-Menutexts */
  168. { 420, NUMBER_OTHER,    TEXT_START_OTHER},    /* all other texts */
  169. { 450, NUMBER_SLIDER,   TEXT_START_SLIDER},   /* Slider texts */
  170. { 460, NUMBER_GADGET,   TEXT_START_GADGET},   /* Gadgettexts */
  171. {   0, 0, 0},                      /* Ende */
  172. };
  173.  
  174. STRPTR text[] =
  175. {
  176. "Project",
  177. "O\0Open...",
  178. "M\0Load Add...",
  179. "A\0Save As...",
  180. "Q\0Quit",
  181. "Edit",
  182. "D\0Reset To Defaults",
  183. "L\0Last Saved",
  184. "R\0Restore",
  185. "Settings",
  186. "I\0Create Icons?",
  187. "XpkMaster Preferences",    /* the window title */
  188. "«default»",            /* the default pack mode */
  189. "«new»",
  190. "Select xpk or xex library",
  191. "Load XpkMaster preferences",
  192. "Save XpkMaster preferences",
  193. "Program Error",
  194. "Error accessing file\n%s\n%s",
  195. "Requires %s V%ld",
  196. "Prefs file version to high,\nloaded data may be incomplete.",
  197. "Error processing IFF file",
  198. "%s of entry %ld (%s)\nis illegal, cannot save.",
  199. "Could not open window,\nthe used font is too large.",
  200. "OK",
  201. "Save",
  202. "Use",
  203. "Cancel",
  204. "Use XFD",            /* the checkboxes */
  205. "Use XEX",
  206. "Auto password",
  207. "Timeout",            /* the timeout integer */
  208. "New",                /* the listview gadget */
  209. "Delete",
  210. "Up",
  211. "Down",
  212. "Name Pattern",
  213. "File Pattern",
  214. "Library Name",
  215. "Mode",
  216. "ChunkSize",
  217. "PackMode",
  218.  
  219. "pack xpk or xex",
  220. "do not pack",
  221. "return error",
  222. 0,
  223. };
  224.  
  225. STRPTR toolt[] =
  226. {
  227. "EDIT",
  228. "USE",
  229. "SAVE",
  230. "PUBSCREEN",
  231. "CREATEICONS",    /* YES || NO */
  232. "ACTION"
  233. };
  234.  
  235. /* ---------------------- protos and variables ------------------------- */
  236.  
  237. struct RDArgs        *rda        = 0;
  238. struct Library        *GadToolsBase    = 0,
  239.             *IconBase    = 0,
  240.             *UtilityBase    = 0,
  241.             *AslBase    = 0,
  242.             *IFFParseBase    = 0;
  243. struct LocaleBase    *LocaleBase    = 0;
  244. struct IntuitionBase    *IntuitionBase    = 0;
  245. struct GfxBase        *GfxBase    = 0;
  246. struct Screen        *Scr        = 0;
  247. APTR            VisualInfo    = 0;
  248. struct Window        *window        = 0;
  249. struct Gadget        *gadgList    = 0,
  250.             *gadgdata[12];
  251. /* List, NamePatt, FilePatt, LibraryName, GetImage, Mode, ChunkSize, Cycle,
  252. TimeOut, XFD, Extern, Pwd */
  253. struct Menu        *menus        = 0;
  254. struct DiskObject    *diskobject    = 0;
  255. ULONG            lock        = 0,
  256.             DosVersion    = 37,
  257.             TimeOut        = DEF_TIMEOUT,
  258.             XPKM_Flags    = DEF_XPKM_FLAGS;
  259. struct ListData        maindata    = {{(struct Node *) &maindata.ld_List.lh_Tail,
  260.      0, (struct Node *) &maindata.ld_List.lh_Head, NT_USER, 0}, 0, 0, 0};
  261. UBYTE            namestring[256];
  262. struct SDI_LocaleData    locdat = {"xpkmasterprefs.catalog", 1, 0,0,0,0};
  263.  
  264. #ifdef __MAXON__
  265. extern "C" void        wbmain(struct WBStartup *);
  266. void            main(void);
  267. #else
  268. void            wbmain(struct WBStartup *);
  269. void            main(int argc, char **argv);
  270. #endif
  271. void            Work(struct Args *);
  272. ULONG            SDIConvToUpper(STRPTR a);
  273.  
  274. void            CorrectAdr(APTR, APTR);
  275. void            CopyStrings(STRPTR, STRPTR, ULONG);
  276. void            CopyLibName(struct XpkTypeData *, struct PackerNode *);
  277. void            ReadXPKM(struct XpkMainPrefs *, struct ListData *);
  278. ULONG            ReadXPKT(struct XpkTypePrefs *, struct ListData *);
  279. ULONG            LoadFile(STRPTR, ULONG);
  280.  
  281. ULONG            CopyData(STRPTR, ULONG *, APTR, STRPTR *);
  282. ULONG            WriteXPKM(struct IFFHandle *);
  283. ULONG            WriteXPKT(struct IFFHandle *, struct PackerNode *, ULONG);
  284. ULONG            SaveFile(STRPTR, ULONG);
  285.  
  286. void            PrintError(STRPTR, ...);
  287. void            FileReq(void);
  288. ULONG            PrefsFileReq(STRPTR, ULONG, STRPTR);
  289. void            FreeListView(void);
  290. void            ResetListView(ULONG, struct ListData *);
  291. void            SetMainData(void);
  292. ULONG             DoWindow(void);
  293.  
  294. void            NewPackerList(struct ListData *);
  295. void            FreePackerList(struct ListData *);
  296. struct Node        *FindNode(struct List *, ULONG);
  297. struct PackerNode    *NewPackerNode(struct ListData *, STRPTR, struct PackerNode *, ULONG);
  298.  
  299. struct NewMenu NewMenus[] = {
  300.   NM_TITLE, (STRPTR) &text[TEXT_START_MENUMAIN],   0, 0, 0, 0,
  301.   NM_ITEM,  (STRPTR) &text[TEXT_START_MENUMAIN+1], 0, 0, 0, 0,
  302.   NM_ITEM,  (STRPTR) &text[TEXT_START_MENUMAIN+2], 0, 0, 0, 0,
  303.   NM_ITEM,  (STRPTR) &text[TEXT_START_MENUMAIN+3], 0, 0, 0, 0,
  304.   NM_ITEM,  (STRPTR) NM_BARLABEL, 0, 0, 0, 0,
  305.   NM_ITEM,  (STRPTR) &text[TEXT_START_MENUMAIN+4], 0, 0, 0, 0,
  306.   NM_TITLE, (STRPTR) &text[TEXT_START_MENUMAIN+5], 0, 0, 0, 0,
  307.   NM_ITEM,  (STRPTR) &text[TEXT_START_MENUMAIN+6], 0, 0, 0, 0,
  308.   NM_ITEM,  (STRPTR) &text[TEXT_START_MENUMAIN+7], 0, 0, 0, 0,
  309.   NM_ITEM,  (STRPTR) &text[TEXT_START_MENUMAIN+8], 0, 0, 0, 0,
  310.   NM_TITLE, (STRPTR) &text[TEXT_START_MENUMAIN+9], 0, 0, 0, 0,
  311.   NM_ITEM,  (STRPTR) &text[TEXT_START_MENUMAIN+10], 0, MENUTOGGLE|CHECKIT, 0, 0,
  312.   NM_END,   0, 0, 0, 0, 0};
  313.  
  314. ULONG PicData[] = {
  315.   0xE3100001,0x00000000,0x0023000F,0x00360017,0x00050003,0x00010044,
  316.   0x39A00000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,
  317.   0x049C004D,0x0CE00033,0x80F88000,0x00008000,0x00000000,0x00000000,
  318.   0x00000000,0x10000000,0x00000036,0x00170002,0x00024288,0x03000000,
  319.   0x00000000,0x00000004,0x00000000,0x00000001,0x00000000,0x07FF8000,
  320.   0x40000000,0x18006000,0x10000000,0x20FC1000,0x08000000,0x41020800,
  321.   0x0C000000,0x40820800,0x0C000000,0x40820800,0x0C000000,0x21040800,
  322.   0x0C000000,0x1E181000,0x0C000000,0x00602000,0x0C000000,0x0080C000,
  323.   0x0C000000,0x01030000,0x0C000000,0x021C0000,0x0C000000,0x01080000,
  324.   0x0C000000,0x00F00000,0x0C000000,0x01080000,0x0C000000,0x01080000,
  325.   0x0C004000,0x00F00000,0x0C001000,0x00000000,0x0C000400,0x00000000,
  326.   0x0C0001FF,0xFFFFFFFF,0xFC000000,0x00000000,0x0000FFFF,0xFFFFFFF8,
  327.   0x0000D555,0x55555556,0x0000D555,0x50005555,0x8000D555,0x47FF9555,
  328.   0x6000D555,0x5F03E555,0x5000D555,0x3E55F555,0x5000D555,0x3F55F555,
  329.   0x5000D555,0x3F55F555,0x5000D555,0x5E53F555,0x5000D555,0x4147E555,
  330.   0x5000D555,0x551FD555,0x5000D555,0x557F1555,0x5000D555,0x54FC5555,
  331.   0x5000D555,0x55E15555,0x5000D555,0x54F55555,0x5000D555,0x55055555,
  332.   0x5000D555,0x54F55555,0x5000D555,0x54F55555,0x50003555,0x55055555,
  333.   0x50000D55,0x55555555,0x50000355,0x55555555,0x50000000,0x00000000,
  334.   0x00000000,0x00000000,0x00000000,0x00145359,0x533A5072,0x6566732F,
  335.   0x58706B4D,0x61737465,0x72000000,0x00080000,0x000B4143,0x54494F4E,
  336.   0x3D555345,0x00000000,
  337. };
  338.  
  339. /* -------------------------- central functions ------------------------ */
  340.  
  341. void wbmain(struct WBStartup *wb)
  342. {
  343.   struct Args args = {0, 0, 0, 0, 0, 0};
  344.  
  345.   if(wb->sm_NumArgs > 2 || !wb->sm_NumArgs)
  346.     End(RETURN_FAIL);
  347.  
  348.   lock = CurrentDir(wb->sm_ArgList[wb->sm_NumArgs-1].wa_Lock);
  349.  
  350.   if((IconBase = OpenLibrary("icon.library", 37)) &&
  351.   (diskobject = GetDiskObject(wb->sm_ArgList[wb->sm_NumArgs-1].wa_Name)))
  352.   {
  353.     STRPTR a, *c = (STRPTR *) diskobject->do_ToolTypes;
  354.  
  355.     if(wb->sm_NumArgs == 2)
  356.       args.from = wb->sm_ArgList[1].wa_Name;
  357.  
  358.     args.edit = (ULONG) FindToolType(c, toolt[0]);
  359.     args.use = (ULONG) FindToolType(c, toolt[1]);
  360.     args.save = (ULONG) FindToolType(c, toolt[2]);
  361.     args.pubscreen = FindToolType(c, toolt[3]);
  362.     if((a = FindToolType(c, toolt[4])))
  363.     {
  364.       if(MatchToolValue(a, "YES"))
  365.         args.createicons = 1;
  366.     }
  367.     if((a = FindToolType(c, toolt[5])))
  368.     {
  369.       if(MatchToolValue(toolt[0], a))
  370.         args.edit = 1;
  371.       else if(MatchToolValue(toolt[1], a))
  372.         args.use = 1;
  373.       else if(MatchToolValue(toolt[2], a))
  374.         args.save = 1;
  375.     }
  376.   }
  377.  
  378.   Work(&args);
  379.   End(RETURN_OK);
  380. }
  381.  
  382. #ifdef __MAXON__
  383. void main(void)
  384. #else
  385. void main(int argc, char **argv)
  386. #endif
  387. {
  388.   struct Args args = {0, 0, 0, 0, 0, 0};
  389.  
  390. #ifdef __SASC
  391.   TestOS;
  392.   if(!argc)
  393.     wbmain((struct WBStartup *) argv);
  394. #endif
  395.  
  396.   if(!(rda = ReadArgs(PARAM, (LONG *) &args, 0)))
  397.     End(RETURN_FAIL);
  398.  
  399.   Work(&args);
  400.   End(RETURN_OK);
  401. }
  402.  
  403. void Work(struct Args *args)
  404. {
  405.   struct IntuiMessage *IntuiMessagePtr;
  406.   ULONG run = 1;
  407.   LONG Long;
  408.   STRPTR txt;
  409.  
  410.   if(args->edit)
  411.     args->use = args->save = 0;
  412.   if(args->save)
  413.     args->use = 0;
  414.  
  415.   if(
  416.   !(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37)) ||
  417.   !(GadToolsBase = OpenLibrary("gadtools.library", 37)) ||
  418.   !(UtilityBase = OpenLibrary("utility.library", 37)) ||
  419.   !(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",37)))
  420.     End(RETURN_FAIL);
  421.  
  422.   SDI_InitLocale(&locdat);
  423.   SDI_LocaleStrings(&locdat, initloc, text);
  424.   SDI_LocaleNewMenu(NewMenus, text + TEXT_START_MENUMAIN,
  425.     text + TEXT_START_OTHER);
  426.  
  427.   if(!(IFFParseBase = OpenLibrary("iffparse.library", 37)))
  428.   {
  429.     PrintError(text[TEXT_LIB_REQUIRED], "iffparse.library", 37);
  430.     End(RETURN_FAIL);
  431.   }
  432.  
  433.   NewPackerList(&maindata);
  434.  
  435.   if(args->use || args->save)
  436.   {
  437.     if(!args->from)
  438.       args->from = "";
  439.     if(LoadFile(args->from, 0) ||
  440.     (args->save && SaveFile((STRPTR)1 , 0)) ||
  441.     SaveFile(0, 0))
  442.       End(RETURN_FAIL);
  443.     End(RETURN_OK);
  444.   }
  445.  
  446.   if(args->createicons)
  447.     NewMenus[11].nm_Flags |= CHECKED;
  448.  
  449.   if(args->from && LoadFile(args->from, 0))
  450.     args->from = 0;
  451.  
  452.   if(!args->from && LoadFile(0, 0))
  453.     LoadFile((STRPTR) 1, 0);
  454.  
  455.   if(!(Scr = LockPubScreen(args->pubscreen)) ||
  456.   !(VisualInfo = GetVisualInfoA(Scr, 0)) ||
  457.   DoWindow())
  458.     End(RETURN_FAIL);
  459.  
  460.   do
  461.   {
  462.     if(Wait((1L<<window->UserPort->mp_SigBit)|SIGBREAKF_CTRL_C)
  463.     == SIGBREAKF_CTRL_C)
  464.       run = 0;
  465.     else
  466.       while(run && (IntuiMessagePtr = GT_GetIMsg(window->UserPort)))
  467.       {
  468.     switch(IntuiMessagePtr->Class)
  469.      {
  470.     case IDCMP_MENUPICK:
  471.       Long = (ULONG) IntuiMessagePtr->Code;
  472.       while(run && (ULONG) Long != MENUNULL)
  473.       {
  474.         switch(MENUNUM((ULONG) Long))
  475.         {
  476.         case 0:                    /* Projekt */
  477.           switch(ITEMNUM((ULONG) Long))
  478.           {
  479.           case 0:                    /* Open... */
  480.         if(PrefsFileReq(args->from, 0, text[TEXT_LOAD_PREFERENCES]))
  481.         {
  482.           args->from = namestring;
  483.           LoadFile(args->from, 0);
  484.                SetMainData();
  485.           ResetListView(0, &maindata);
  486.         }
  487.         break;
  488.           case 1:                    /* Load Add... */
  489.         if(PrefsFileReq(args->from, 0, text[TEXT_LOAD_PREFERENCES]))
  490.         {
  491.           args->from = namestring;
  492.           LoadFile(args->from, 1);
  493.               ResetListView(0, &maindata);
  494.         }
  495.         break;
  496.           case 2:                    /* Save As... */
  497.         if(PrefsFileReq(args->from, 1, text[TEXT_SAVE_PREFERENCES]))
  498.         {
  499.           args->from = namestring;
  500.           SaveFile(args->from, args->createicons);
  501.         }
  502.         break;
  503.           case 4: run = 0; break;            /* Quit */
  504.           } break;
  505.         case 1:                    /* Edit */
  506.           switch(ITEMNUM((ULONG) Long))
  507.           {
  508.           case 0:                /* Reset To Defaults */
  509.         NewPackerList(&maindata);
  510.         ResetListView(0, &maindata);
  511.         break;
  512.           case 1:                    /* Last Saved */
  513.         LoadFile((STRPTR) 1, 0);
  514.         SetMainData();
  515.             ResetListView(0, &maindata);
  516.         break;
  517.           case 2:                    /* Restore */
  518.         LoadFile(0, 0);
  519.             SetMainData();
  520.         ResetListView(0, &maindata);
  521.         break;
  522.           } break;
  523.         case 2:                    /* Settings */
  524.           args->createicons =
  525.           ItemAddress(menus, (ULONG) Long)->Flags & CHECKED;
  526.           break;
  527.         }
  528.         Long = (ULONG) ItemAddress(menus, (ULONG) Long)->NextSelect;
  529.       } break;
  530.     case IDCMP_GADGETUP:
  531.       switch(GADGET(IntuiMessagePtr)->GadgetID)
  532.       {
  533.       case STRING_TypeName:
  534.         txt = STRINF(GADGET(IntuiMessagePtr))->Buffer;
  535.         FreeListView();
  536.         CopyMem(txt, maindata.ld_curNode->pn_TypeName, TypeSIZE);
  537.         ResetListView(~0, &maindata);
  538.         break;
  539.       case LISTVIEW: ResetListView(IntuiMessagePtr->Code, &maindata); break;
  540.       case BUTTON_New:
  541.         FreeListView();
  542.         if(!NewPackerNode(&maindata, text[TEXT_ENTRY_NEW],
  543.         DEFNODE(&maindata), maindata.ld_curNumber))
  544.           End(RETURN_FAIL);
  545.         ResetListView(~0, &maindata); break;
  546.       case BUTTON_Delete:
  547.         if(maindata.ld_curNumber)
  548.         {
  549.           FreeListView();
  550.           Remove((struct Node *) maindata.ld_curNode);
  551.           FreeMem(maindata.ld_curNode, sizeof(struct PackerNode));
  552.           if(--maindata.ld_entries == maindata.ld_curNumber)
  553.             --maindata.ld_curNumber;
  554.           ResetListView(~0, &maindata);
  555.         } break;
  556.       case BUTTON_Up:
  557.         if(maindata.ld_curNumber > 1)
  558.         {
  559.           struct Node *p;
  560.           FreeListView();
  561.           p = maindata.ld_curNode->pn_Node.ln_Pred->ln_Pred;
  562.           Remove((struct Node *) maindata.ld_curNode);
  563.           Insert(&maindata.ld_List, (struct Node *) maindata.ld_curNode, p);
  564.           ResetListView(--maindata.ld_curNumber, &maindata);
  565.         } break;
  566.       case BUTTON_Down:
  567.         if(maindata.ld_curNumber &&
  568.         maindata.ld_curNumber != maindata.ld_entries - 1)
  569.         {
  570.           struct Node *p;
  571.           FreeListView();
  572.           p = maindata.ld_curNode->pn_Node.ln_Succ;
  573.           Remove((struct Node *) maindata.ld_curNode);
  574.           Insert(&maindata.ld_List, (struct Node *) maindata.ld_curNode, p);
  575.           ResetListView(++maindata.ld_curNumber, &maindata);
  576.         } break;
  577.       case STRING_NamePatt:
  578.         txt = STRINF(GADGET(IntuiMessagePtr))->Buffer;
  579. /* add test for correct pattern here */
  580.         CopyMem(txt, &maindata.ld_curNode->pn_NamePattern, NamePattSIZE);
  581.         break;
  582.       case STRING_FilePatt:
  583.         txt = STRINF(GADGET(IntuiMessagePtr))->Buffer;
  584. /* add test for correct pattern here */
  585.         CopyMem(txt, &maindata.ld_curNode->pn_FilePattern, FilePattSIZE);
  586.         break;
  587.       case GETIMAGE: FileReq(); GT_SetGadgetAttrs(gadgdata[3], window,
  588.         0, GTST_String, &maindata.ld_curNode->pn_StdID, GA_Disabled,
  589.         maindata.ld_curNode->pn_Cycle, TAG_DONE);
  590.         break;
  591.       case STRING_LibraryName:
  592.         txt = STRINF(GADGET(IntuiMessagePtr))->Buffer;
  593.         if((Long = SDIConvToUpper(txt)))
  594.         {
  595.           maindata.ld_curNode->pn_StdID = Long;
  596.           GT_SetGadgetAttrs(gadgdata[3], window,
  597.           0, GTST_String, &maindata.ld_curNode->pn_StdID, GA_Disabled,
  598.           maindata.ld_curNode->pn_Cycle, TAG_DONE);
  599.         }
  600.         else
  601.         {
  602.           DisplayBeep(Scr);
  603.           ActivateGadget(GADGET(IntuiMessagePtr), window,0);
  604.         }
  605.         break;
  606.       case INTEGER_Mode:
  607.         Long = STRINF(GADGET(IntuiMessagePtr))->LongInt;
  608.         if((Long > 100) || (Long < 0))
  609.         {
  610.           DisplayBeep(Scr);
  611.           ActivateGadget(GADGET(IntuiMessagePtr), window,0);
  612.         }
  613.         else maindata.ld_curNode->pn_Mode = Long;
  614.         break;
  615.       case INTEGER_ChunkSize:
  616.         Long = STRINF(GADGET(IntuiMessagePtr))->LongInt;
  617.         if(Long < 0)
  618.         {
  619.           DisplayBeep(Scr);
  620.           ActivateGadget(GADGET(IntuiMessagePtr), window,0);
  621.         }
  622.         else maindata.ld_curNode->pn_ChunkSize = Long;
  623.         break;
  624.       case CYCLE: maindata.ld_curNode->pn_Cycle = IntuiMessagePtr->Code;
  625.         ResetListView(~0, &maindata); break;
  626.       case INTEGER_TimeOut:
  627.         Long = STRINF(GADGET(IntuiMessagePtr))->LongInt;
  628.         if(Long < 0 || Long > 0xFFFF)
  629.         {
  630.           DisplayBeep(Scr);
  631.           ActivateGadget(GADGET(IntuiMessagePtr), window,0);
  632.         }
  633.         else TimeOut = Long;
  634.         break;
  635.       case CHECKBOX_XFD:
  636.         XPKM_Flags ^= XPKM_UseXFD; break;
  637.       case CHECKBOX_EXT:
  638.         XPKM_Flags ^= XPKM_UseExternals; break;
  639.       case CHECKBOX_Password:
  640.         XPKM_Flags ^= XPKM_AutoPassword; break;
  641.       case BUTTON_Save:
  642.         if(!SaveFile((STRPTR) 1, 0))
  643.           if(!SaveFile(0, 0))
  644.         run = 0;
  645.          break;
  646.       case BUTTON_Use: if(!SaveFile(0, 0)) run = 0; break;
  647.       case BUTTON_Chancel: run = 0; break;
  648.       } break;
  649.     }
  650.         GT_ReplyIMsg(IntuiMessagePtr);
  651.       }
  652.   }
  653.   while(run);
  654. }
  655.  
  656. ULONG SDIConvToUpper(STRPTR b)
  657. {
  658.   ULONG i;
  659.   ULONG out = 0;
  660.  
  661.   for(i = 0; i < 4; ++i)
  662.   {
  663.     if(!SDI_isalnum(b[i]))
  664.       return 0;
  665.     out = (out<<8) + SDI_toupper(b[i]);
  666.   }
  667.  
  668.   return out;
  669. }
  670.  
  671. /* ----------------------- loading functions --------------------------- */
  672.  
  673. void CorrectAdr(APTR pos, APTR mempos)
  674. { /* changes relative addresses into normal ones */
  675.   if(*(ULONG *)pos)
  676.     *(ULONG *)pos += (ULONG) mempos;
  677. }
  678.  
  679. void CopyStrings(STRPTR from, STRPTR to, ULONG Size)
  680. {
  681.   ULONG i;
  682.  
  683.   if(from)
  684.   {
  685.     if((i = SDI_strlen(from)) > Size)
  686.       i = Size;
  687.     CopyMem(from, to, i);
  688.   }
  689. }
  690.  
  691. void CopyLibName(struct XpkTypeData *p, struct PackerNode *n)
  692. {
  693.   if(p->xtd_Flags & XTD_NoPack)
  694.     n->pn_Cycle = 1;
  695.   else if(p->xtd_Flags & XTD_ReturnError || !p->xtd_StdID)
  696.     n->pn_Cycle = 2;
  697.   else
  698.   {
  699.     n->pn_Cycle = 0;
  700.     n->pn_StdID = p->xtd_StdID;
  701.   }
  702. }
  703.  
  704. void ReadXPKM(struct XpkMainPrefs *pref, struct ListData *dat)
  705. {
  706.   struct PackerNode *n = DEFNODE(dat);
  707.   struct XpkTypeData *p;
  708.  
  709.   CorrectAdr(&pref->xmp_DefaultType, pref);
  710.   p = pref->xmp_DefaultType;
  711.   CopyLibName(p, n);
  712.   n->pn_Mode = p->xtd_Mode;
  713.   n->pn_ChunkSize = p->xtd_ChunkSize;
  714.   TimeOut = pref->xmp_Timeout;
  715.   XPKM_Flags = pref->xmp_Flags;
  716. }
  717.  
  718. ULONG ReadXPKT(struct XpkTypePrefs *pref, struct ListData *dat)
  719. {
  720.   struct PackerNode *n;
  721.  
  722.   CorrectAdr(&pref->xtp_NamePattern, pref);
  723.   CorrectAdr(&pref->xtp_FilePattern, pref);
  724.   CorrectAdr(&pref->xtp_TypeName, pref);
  725.   CorrectAdr(&pref->xtp_PackerData, pref);
  726.   if(!pref->xtp_TypeName)
  727.     pref->xtp_TypeName = text[TEXT_ENTRY_NEW];
  728.  
  729.   if(!(n = NewPackerNode(dat, pref->xtp_TypeName, 0, dat->ld_curNumber)))
  730.     return 2;
  731.  
  732.   CopyStrings(pref->xtp_NamePattern, n->pn_NamePattern, NamePattSIZE);
  733.   CopyStrings(pref->xtp_FilePattern, n->pn_FilePattern, FilePattSIZE);
  734.   CopyLibName(pref->xtp_PackerData, n);
  735.   n->pn_Mode = pref->xtp_PackerData->xtd_Mode;
  736.   n->pn_ChunkSize = pref->xtp_PackerData->xtd_ChunkSize;
  737.   return 0;
  738. }
  739.  
  740. ULONG LoadFile(STRPTR file, ULONG addmode)
  741. {
  742. /* addmode only processes PRHD and XPKT chunks (not XPKM) -- adds the
  743.    chunks to the list -- no replacement */
  744.  
  745.   struct ContextNode  *cn;
  746.   struct IFFHandle *iff;
  747.   ULONG data = (ULONG) file > 1 ? 1 : 0;
  748.   ULONG error = 0;
  749.  
  750.   if(file == (STRPTR) 1)
  751.     file = "ENVARC:xpkmaster.prefs";
  752.   else if(!file)
  753.     file = "ENV:xpkmaster.prefs";
  754.  
  755.   if((iff = AllocIFF()))
  756.   {
  757.     if((iff->iff_Stream = Open(file, MODE_OLDFILE)))
  758.     {
  759.       InitIFFasDOS(iff);
  760.       if(!(error = OpenIFF(iff, IFFF_READ)))
  761.       {
  762.     LONG a[] = { ID_PREF, ID_PRHD, ID_PREF, ID_XPKT, ID_PREF, ID_XPKM};
  763.     if(!(error = StopChunks(iff, a, 3)))
  764.     {
  765.       STRPTR buf;
  766.       ULONG Flags = (addmode ? 2 : 0);
  767.  
  768.       while(!error)
  769.           {
  770.             if((error = ParseIFF(iff,IFFPARSE_SCAN)))
  771.               break;
  772.  
  773.             cn = CurrentChunk(iff);
  774.  
  775.         if(!addmode && cn->cn_ID != ID_PRHD)
  776.         {    /* clear list only when XPKT or XPKM and not addmode */
  777.           NewPackerList(&maindata); addmode = 1;
  778.         }
  779.  
  780.         if((buf = (STRPTR) AllocMem(cn->cn_Size, MEMF_ANY|MEMF_CLEAR)))
  781.         {
  782.           ReadChunkBytes(iff,buf,cn->cn_Size);
  783.           switch(cn->cn_ID)
  784.           {
  785.           case ID_PRHD:
  786.         if(!(Flags & 1))
  787.         {
  788.           if(((struct PrefHeader *) buf)->ph_Version > PREF_VERSION)
  789.             PrintError(text[TEXT_VERSION_TO_HIGH]);
  790.           Flags |= 1;
  791.         } break;
  792.           case ID_XPKM:
  793.         if(!(Flags & 2))
  794.         {
  795.           ReadXPKM((struct XpkMainPrefs *) buf, &maindata);
  796.           Flags |= 2;
  797.         } break;
  798.           case ID_XPKT:
  799.         error = ReadXPKT((struct XpkTypePrefs *) buf, &maindata);
  800.         break;
  801.           }
  802.           FreeMem(buf, cn->cn_Size);
  803.         }
  804.         else error = 2;
  805.       }
  806.       if(error == IFFERR_EOF)
  807.         error = 0;
  808.     }
  809.         CloseIFF(iff);
  810.       }
  811.       Close(iff->iff_Stream);
  812.     }
  813.     else if(data)
  814.     {
  815.       UBYTE err[100];
  816.       Fault(IoErr(), 0, err, 100);
  817.       PrintError(text[TEXT_ERROR_FILEACCESS], file, &err);
  818.       error = 1;
  819.     }
  820.     else
  821.       error = 1;
  822.     FreeIFF(iff);
  823.   }
  824.  
  825.   if(error && error != 1)
  826.     PrintError(text[TEXT_ERROR_FILEPROCESS]);
  827.  
  828.   return error;
  829. }
  830.  
  831. /* ----------------------- saving functions ---------------------------- */
  832.  
  833. ULONG CopyData(STRPTR from, ULONG *to, APTR data, STRPTR *entry)
  834. {
  835.   ULONG i = SDI_strlen(from);
  836.  
  837.   if(!(*from))
  838.     return 0;
  839.   CopyMem(from, (STRPTR) data + *to, i);
  840.   *entry = (STRPTR) *to;
  841.   *to += ++i;
  842. }
  843.  
  844. #define XPKM_Size    (sizeof(struct XpkMainPrefs) + \
  845.             sizeof(struct XpkTypeData))
  846.  
  847. #define    xpkm    ((struct XpkMainPrefs *) data)
  848. #define xpkd    ((struct XpkTypeData *) (data + sizeof(struct XpkMainPrefs)))
  849.  
  850. ULONG WriteXPKM(struct IFFHandle *iff)
  851. {
  852.   STRPTR data;
  853.   struct PackerNode *r = DEFNODE(&maindata);
  854.   ULONG ptr = sizeof(struct XpkMainPrefs), error;
  855.  
  856.   if(!r->pn_Cycle && !r->pn_StdID)
  857.   {
  858.     PrintError(text[TEXT_ILLEGAL_ENTRY], text[GADG_Library_Name], 1, r->pn_TypeName);
  859.     return 1;
  860.   }
  861.  
  862.   if((data = (STRPTR) AllocMem(XPKM_Size, MEMF_ANY|MEMF_CLEAR)))
  863.   {
  864. //    xpkm->xmp_Version        = 0;    /* structure version */
  865.     xpkm->xmp_Flags        = XPKM_Flags;
  866.     xpkm->xmp_Timeout        = TimeOut;
  867.     xpkm->xmp_DefaultType    = (struct XpkTypeData *) ptr;
  868.     ptr += sizeof(struct XpkTypeData);
  869.  
  870.     switch(r->pn_Cycle)
  871.     {
  872.     case 0:
  873.       xpkd->xtd_Mode = r->pn_Mode;
  874.       xpkd->xtd_ChunkSize = r->pn_ChunkSize;
  875.       xpkd->xtd_StdID = r->pn_StdID;
  876.       break;
  877.     case 1: xpkd->xtd_Flags |= XTD_NoPack; break;
  878.     case 2: xpkd->xtd_Flags |= XTD_ReturnError; break;
  879.     }
  880.  
  881.     if(!(error = PushChunk(iff, 0, ID_XPKM, ptr)))
  882.     {
  883.       if(WriteChunkBytes(iff, data, ptr) != ptr)
  884.     error = 3;
  885.       else
  886.     error = PopChunk(iff);
  887.     }
  888.     FreeMem(data, XPKM_Size);
  889.   }
  890.   else
  891.     error = 2;
  892.  
  893.   return error;
  894. }
  895.  
  896. #define xpkt        ((struct XpkTypePrefs *) data)
  897. #define xtd        ((struct XpkTypeData *) (data + sizeof(struct XpkTypePrefs)))
  898.  
  899. #define XPKT_Size    (TypeSIZE + 1 + NamePattSIZE + 1 + \
  900.             FilePattSIZE + 1 + sizeof(struct XpkTypePrefs)) \
  901.             + sizeof(struct XpkTypeData)
  902.  
  903. ULONG WriteXPKT(struct IFFHandle *iff, struct PackerNode *r, ULONG num)
  904. {
  905.   STRPTR data;
  906.   ULONG error, ptr = sizeof(struct XpkTypePrefs) + sizeof(struct XpkTypeData);
  907.  
  908.   if(!r->pn_Cycle && !r->pn_StdID)
  909.   {
  910.     PrintError(text[TEXT_ILLEGAL_ENTRY], text[GADG_Library_Name], num+1, r->pn_TypeName);
  911.     return 1;
  912.   }
  913.   else if(!r->pn_NamePattern[0] && !r->pn_FilePattern[0])
  914.   {
  915.     PrintError(text[TEXT_ILLEGAL_ENTRY], text[GADG_File_Pattern], num+1, r->pn_TypeName);
  916.     return 1;
  917.   }
  918.  
  919.   if((data = (STRPTR) AllocMem(XPKT_Size, MEMF_ANY|MEMF_CLEAR)))
  920.   {
  921.     if(CopyData(r->pn_NamePattern, &ptr, data, &xpkt->xtp_NamePattern))
  922.       xpkt->xtp_Flags |= XPKT_NamePattern;
  923.     if(CopyData(r->pn_FilePattern, &ptr, data, &xpkt->xtp_FilePattern))
  924.       xpkt->xtp_Flags |= XPKT_FilePattern;
  925.     CopyData(r->pn_TypeName, &ptr, data, &xpkt->xtp_TypeName);
  926.     xpkt->xtp_PackerData = (struct XpkTypeData *) sizeof(struct XpkTypePrefs);
  927.  
  928.     switch(r->pn_Cycle)
  929.     {
  930.     case 0:
  931.       xtd->xtd_Mode = r->pn_Mode;
  932.       xtd->xtd_ChunkSize = r->pn_ChunkSize;
  933.       xtd->xtd_StdID = r->pn_StdID;
  934.       break;
  935.     case 1: xtd->xtd_Flags |= XTD_NoPack; break;
  936.     case 2: xtd->xtd_Flags |= XTD_ReturnError; break;
  937.     }
  938.  
  939.     if(!(error = PushChunk(iff, 0, ID_XPKT, ptr)))
  940.     {
  941.       if(WriteChunkBytes(iff, data, ptr) != ptr)
  942.     error = 3;
  943.       else
  944.     error = PopChunk(iff);
  945.     }
  946.     FreeMem(data, XPKT_Size);
  947.   }
  948.   else
  949.     error = 2;
  950.  
  951.   return error;
  952. }
  953.  
  954. ULONG SaveFile(STRPTR file, ULONG icons)
  955. {
  956.   struct IFFHandle *iff;
  957.   ULONG error = 0;
  958.  
  959.   if(file == (STRPTR) 1)
  960.     file = "ENVARC:xpkmaster.prefs";
  961.   else if(!file)
  962.     file = "ENV:xpkmaster.prefs";
  963.  
  964.   if((iff = AllocIFF()))
  965.   {
  966.     if((iff->iff_Stream = Open(file, MODE_NEWFILE)))
  967.     {
  968.       InitIFFasDOS(iff);
  969.       if(!(error = OpenIFF(iff, IFFF_WRITE)))
  970.       {
  971.         if(!(error = PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN)))
  972.         {
  973.           if(!(error = PushChunk(iff, 0, ID_PRHD, sizeof(struct PrefHeader))))
  974.           {
  975.         struct PrefHeader a = {PREF_VERSION, 0, 0};
  976.         if(WriteChunkBytes(iff, &a, sizeof(struct PrefHeader))
  977.         == sizeof(struct PrefHeader))
  978.         {
  979.           if(!(error = PopChunk(iff)))
  980.           {
  981.             if(!(error = WriteXPKM(iff)))
  982.             {
  983.           struct Node *n = FindNode(&maindata.ld_List, 1);
  984.           ULONG num = 1, a;
  985.           for(a = maindata.ld_entries-1; a; --a)
  986.           {
  987.             if((error = WriteXPKT(iff, (struct PackerNode *) n, num)))
  988.               break;
  989.             n = n->ln_Succ; ++num;
  990.           }
  991.             }
  992.           }
  993.         }
  994.         else
  995.           error = 2;
  996.       }
  997.       if(!error)
  998.         error = PopChunk(iff);
  999.     }
  1000.         CloseIFF(iff);
  1001.       }
  1002.       Close(iff->iff_Stream);
  1003.       if(error)
  1004.           DeleteFile(file);
  1005.     }
  1006.     else
  1007.     {
  1008.       UBYTE err[100];
  1009.       Fault(IoErr(), 0, err, 100);
  1010.       PrintError(text[TEXT_ERROR_FILEACCESS], file, &err);
  1011.       error = 1;
  1012.     }
  1013.     FreeIFF(iff);
  1014.   }
  1015.  
  1016.   if(!error && icons)
  1017.   {
  1018.     ULONG i = SDI_strlen(file);
  1019.     STRPTR a;
  1020.  
  1021.     if((a = (STRPTR) AllocMem(i+1+5, MEMF_ANY)))
  1022.     {
  1023.       ULONG fh;
  1024.  
  1025.       CopyMem(file, a, i);
  1026.       CopyMem(".info", a+i, 6);
  1027.       if((fh = Open(a, MODE_NEWFILE)))
  1028.       {
  1029.     Write(fh, PicData, PicSize);
  1030.     Close(fh);
  1031.       }
  1032.       FreeMem(a, i+1+5);
  1033.     }
  1034.   }
  1035.  
  1036.   if(error && error != 1)
  1037.     PrintError(text[TEXT_ERROR_FILEPROCESS]);
  1038.  
  1039.   return error;
  1040. }
  1041.  
  1042. /* ---------------------- graphics functions --------------------------- */
  1043.  
  1044. void PrintError(STRPTR txt, ...)
  1045. {
  1046.   struct EasyStruct easystruct;
  1047.  
  1048.   SDI_memset(&easystruct, 0, sizeof(struct EasyStruct));
  1049.  
  1050.   easystruct.es_StructSize = sizeof(struct EasyStruct);
  1051.   easystruct.es_Title = text[TEXT_TITLE_ERR_REQUEST];
  1052.   easystruct.es_TextFormat = txt;
  1053.   easystruct.es_GadgetFormat = text[GADGS_ERR_REQUEST];
  1054.  
  1055.   EasyRequestArgs(window, &easystruct, 0, (APTR)
  1056.   ((ULONG) &txt + sizeof(STRPTR)));
  1057. }
  1058.  
  1059. void FileReq(void)
  1060. {
  1061.   ULONG Long;
  1062.   UBYTE libname[] = "x..____.library";
  1063.   struct FileRequester *r;
  1064.  
  1065.   CopyMem(&maindata.ld_curNode->pn_StdID, libname+3, 4);
  1066.   if(libname[3] == 'X')
  1067.   {
  1068.     libname[1] = 'e'; libname[2] = 'x';
  1069.   }
  1070.   else
  1071.   {
  1072.     libname[1] = 'p'; libname[2] = 'k';
  1073.   }
  1074.  
  1075.   if((AslBase = OpenLibrary("asl.library", 37)))
  1076.   {
  1077.     if((r = (struct FileRequester *) AllocAslRequest(ASL_FileRequest, 0)))
  1078.     {
  1079.       if((AslRequestTags(r, ASLFR_TitleText, text[TEXT_SELECT_LIBRARY],
  1080.     ASLFR_InitialFile, libname,
  1081.     ASLFR_InitialDrawer, "LIBS:compressors", ASLFR_DoSaveMode, FALSE,
  1082.     ASLFR_InitialPattern, "(xpk|xex)????.library", TAG_DONE)))
  1083.         if((!SDI_strncmp(r->fr_File, "xpk", 3) ||
  1084.         !SDI_strncmp(r->fr_File, "xex", 3) &&
  1085.         !SDI_strcmp(r->fr_File+7, ".library")) &&
  1086.         (Long = SDIConvToUpper(r->fr_File+3)))
  1087.       maindata.ld_curNode->pn_StdID = Long;
  1088.     else
  1089.       DisplayBeep(Scr);
  1090.       FreeAslRequest(r);
  1091.     }
  1092.     CloseLibrary(AslBase);
  1093.     AslBase = 0;
  1094.   }
  1095.   else
  1096.     PrintError(text[TEXT_LIB_REQUIRED], "asl.library", 37);
  1097. }
  1098.  
  1099. ULONG PrefsFileReq(STRPTR dir, ULONG mode, STRPTR title)
  1100. {
  1101.   ULONG error = 0;
  1102.   struct FileRequester *r;
  1103.  
  1104.   if((AslBase = OpenLibrary("asl.library", 37)))
  1105.   {
  1106.     if((r = (struct FileRequester *) AllocAslRequest(ASL_FileRequest, 0)))
  1107.     {
  1108.       UBYTE d[200], *f = 0;
  1109.  
  1110.       if(dir)
  1111.       {
  1112.         CopyMem(dir, d, 200);
  1113.         if((f = FilePart(dir)))
  1114.         d[f-dir] = 0;
  1115.       }
  1116.       
  1117.       if((AslRequestTags(r, ASLFR_TitleText, title,
  1118.     ASLFR_InitialDrawer, dir ? d : "SYS:Prefs/Presets",
  1119.     ASLFR_DoSaveMode, mode,    (f ? ASLFR_InitialFile : TAG_DONE), f,
  1120.     TAG_DONE)))
  1121. /* only give ASLFR_InitialFile, when f is not zero, because else
  1122.    asl.library makes Enforcer hit! */
  1123.       {
  1124.         CopyMem(r->fr_Drawer, namestring, SDI_strlen(r->fr_Drawer)+1);
  1125.         AddPart(namestring, r->fr_File, 256);
  1126.         error = 1;
  1127.       }
  1128.       FreeAslRequest(r);
  1129.     }
  1130.     CloseLibrary(AslBase);
  1131.     AslBase = 0;
  1132.   }
  1133.   else
  1134.     PrintError(text[TEXT_LIB_REQUIRED], "asl.library", 37);
  1135.  
  1136.   return error;
  1137. }
  1138.  
  1139. void FreeListView(void)
  1140. {
  1141.   GT_SetGadgetAttrs(gadgdata[0], window, 0, GTLV_Labels, ~0, TAG_DONE);
  1142. }
  1143.  
  1144. void ResetListView(ULONG number, struct ListData *dat)
  1145. {
  1146.   STRPTR lib = "";
  1147.  
  1148.   if(number == ~0)
  1149.     number = dat->ld_curNumber;
  1150.   dat->ld_curNode = (struct PackerNode *) FindNode(&dat->ld_List, number);
  1151.  
  1152.   /* NamePattern */
  1153.   GT_SetGadgetAttrs(gadgdata[1], window, 0, GTST_String,
  1154.   dat->ld_curNode->pn_NamePattern, GA_Disabled, !number, TAG_DONE);
  1155.  
  1156.   /* FilePattern */
  1157.   GT_SetGadgetAttrs(gadgdata[2], window, 0, GTST_String,
  1158.   dat->ld_curNode->pn_FilePattern, GA_Disabled, !number, TAG_DONE);
  1159.  
  1160.   /* Cycle */
  1161.   GT_SetGadgetAttrs(gadgdata[7], window, 0, GTCY_Active,
  1162.   dat->ld_curNode->pn_Cycle, TAG_DONE);
  1163.  
  1164.   /* Listview */
  1165.   GT_SetGadgetAttrs(gadgdata[0], window, 0, GTLV_Labels, &dat->ld_List,
  1166.   GTLV_Selected, number, GTLV_Top, ((LONG) number - 5 < 0 ?
  1167.   0 : number - 5), TAG_DONE);
  1168.  
  1169.   if(dat->ld_curNode->pn_StdID)
  1170.     lib = (STRPTR) &dat->ld_curNode->pn_StdID;
  1171.  
  1172.   /* Name */
  1173.   GT_SetGadgetAttrs(gadgdata[3], window, 0, GTST_String,
  1174.   lib, GA_Disabled, dat->ld_curNode->pn_Cycle, TAG_DONE);
  1175.  
  1176.   /* GetImage */
  1177.   GT_SetGadgetAttrs(gadgdata[4], window, 0, GA_Disabled,
  1178.   dat->ld_curNode->pn_Cycle, TAG_DONE);
  1179.  
  1180.   /* Mode */
  1181.   GT_SetGadgetAttrs(gadgdata[5], window, 0, GTIN_Number,
  1182.   dat->ld_curNode->pn_Mode, GA_Disabled, dat->ld_curNode->pn_Cycle,
  1183.   TAG_DONE);
  1184.  
  1185.   /* ChunkSize */
  1186.   GT_SetGadgetAttrs(gadgdata[6], window, 0, GTIN_Number,
  1187.   dat->ld_curNode->pn_ChunkSize, GA_Disabled, dat->ld_curNode->pn_Cycle,
  1188.   TAG_DONE);
  1189.  
  1190.   dat->ld_curNumber = number;
  1191. }
  1192.  
  1193. void SetMainData(void)
  1194. {
  1195.   ULONG i;
  1196.  
  1197.   for(i = 0; i < 3; i++)
  1198.   {
  1199.     GT_SetGadgetAttrs(gadgdata[9+i], window, 0, GTCB_Checked,
  1200.     XPKM_Flags & (1<<i), TAG_DONE);
  1201.   }
  1202.   GT_SetGadgetAttrs(gadgdata[8], window, 0, GTIN_Number, TimeOut, TAG_DONE);
  1203. }
  1204.  
  1205. ULONG DoWindow(void)
  1206. {
  1207.   UWORD    winwidth, winheight;
  1208.   STRPTR *txt = text + GADG_New;
  1209.   ULONG i, j, k;
  1210.   struct Gadget        *g;
  1211.   struct NewGadget    ng;
  1212.  
  1213.   SDI_memset(&ng, 0, sizeof(struct NewGadget));
  1214.  
  1215.   ng.ng_LeftEdge = Scr->WBorLeft + SEPARATE_BORD;
  1216.   ng.ng_TopEdge = Scr->WBorTop + Scr->Font->ta_YSize + 1 + SEPARATE_BORD;
  1217.   ng.ng_Height = Scr->Font->ta_YSize+5;
  1218.   ng.ng_TextAttr = Scr->Font;
  1219.   ng.ng_GadgetID = 100;
  1220.   ng.ng_VisualInfo = VisualInfo;
  1221.  
  1222.   if(!(g = CreateContext(&gadgList)))
  1223.     return 1;
  1224.  
  1225.   for(i = k = 0; i < 4; ++i)
  1226.   {
  1227.     ng.ng_Width = 7 + TextLength(&Scr->RastPort, txt[i], SDI_strlen(txt[i]));
  1228.     if(ng.ng_Width > k)
  1229.       k = ng.ng_Width;
  1230.   }
  1231.   ng.ng_Width = k << 2;
  1232.  
  1233.   if(!(g = CreateGadget(STRING_KIND, g, &ng, GTST_MaxChars, TypeSIZE, TAG_DONE)))
  1234.     return 2;
  1235.   ++ng.ng_GadgetID;
  1236.  
  1237.   ng.ng_Height *= 10;
  1238.  
  1239.   if(!(gadgdata[0] = g = CreateGadget(LISTVIEW_KIND,g,&ng,
  1240.   GTLV_ShowSelected, g, TAG_DONE)))
  1241.     return 3;
  1242.  
  1243.   ++ng.ng_GadgetID;
  1244.   ng.ng_LeftEdge = Scr->WBorLeft + SEPARATE_BORD;
  1245.   ng.ng_TopEdge += g->Height + Scr->Font->ta_YSize+5;
  1246.   ng.ng_Height = Scr->Font->ta_YSize+5;
  1247.   ng.ng_Flags = PLACETEXT_IN;
  1248.   ng.ng_Width = k;
  1249.  
  1250.   for(i = 0; i < 4; ++i)
  1251.   {
  1252.     ng.ng_GadgetText = *(txt++);
  1253.     if(!(g = CreateGadgetA(BUTTON_KIND, g, &ng, 0)))
  1254.       return 4;
  1255.     ++ng.ng_GadgetID;
  1256.     ng.ng_LeftEdge += ng.ng_Width;
  1257.   }
  1258.  
  1259.   winheight = ng.ng_TopEdge + ng.ng_Height + SEPARATE_DIFF;
  1260.  
  1261.   ng.ng_TopEdge = Scr->WBorTop + Scr->Font->ta_YSize + 1 + SEPARATE_BORD;
  1262.   txt = text + GADG_Name_Pattern;
  1263.  
  1264.   for(i = k = 0; i < 6; ++i)
  1265.   {
  1266.     j = 7 + TextLength(&Scr->RastPort, txt[i], SDI_strlen(txt[i]));
  1267.     if(j > k)
  1268.       k = j;
  1269.   }
  1270.  
  1271.   j = ng.ng_LeftEdge + SEPARATE_DIFF; /* store startpos */
  1272.   ng.ng_LeftEdge = j + k;
  1273.  
  1274.   ng.ng_Width = 0;
  1275.   for(i = 0; i < 3; ++i)
  1276.   {
  1277.     STRPTR *tx = text + TEXT_START_SLIDER;
  1278.     k = 50 + TextLength(&Scr->RastPort, tx[i], SDI_strlen(tx[i]));
  1279.     if(k > ng.ng_Width)
  1280.       ng.ng_Width = k;
  1281.   } /* width of gadgets is the one of the cycle gadget */
  1282.  
  1283.   ng.ng_Flags = PLACETEXT_LEFT;
  1284.   winwidth = ng.ng_LeftEdge + ng.ng_Width; /* set resulting window width */
  1285.  
  1286.   for(i = 0; i < 2; ++i)
  1287.   {
  1288.     ng.ng_GadgetText = *(txt++);
  1289.     if(!(gadgdata[i+1] = g = CreateGadget(STRING_KIND,g,&ng, GTST_MaxChars,
  1290.     (i ? FilePattSIZE : NamePattSIZE), TAG_DONE)))
  1291.       return 5;
  1292.     ++ng.ng_GadgetID;
  1293.     ng.ng_TopEdge += ng.ng_Height + SEPARATE_SAME;
  1294.   }
  1295.  
  1296.   ng.ng_Width -= ng.ng_Height;
  1297.   ng.ng_GadgetText = *(txt++);
  1298.   if(!(gadgdata[3] = g = CreateGadget(STRING_KIND,g,&ng, GTST_MaxChars, 4,
  1299.   STRINGA_Justification, GACT_STRINGCENTER, TAG_DONE)))
  1300.     return 6;
  1301.   ++ng.ng_GadgetID;
  1302.   ng.ng_GadgetText = 0;
  1303.   k = ng.ng_Width;
  1304.   ng.ng_Width = ng.ng_Height;
  1305.   ng.ng_LeftEdge += k;
  1306.   if(!(gadgdata[4] = g = CreateGadgetA(BUTTON_KIND,g,&ng, 0)))
  1307.     return 7;
  1308.   ng.ng_LeftEdge -= k;
  1309.   ng.ng_Width += k;
  1310.   ++ng.ng_GadgetID;
  1311.   ng.ng_TopEdge += ng.ng_Height + SEPARATE_SAME;
  1312.  
  1313.   for(i = 0; i < 2; ++i)
  1314.   {
  1315.     ng.ng_GadgetText = *(txt++);
  1316.     if(!(gadgdata[i+5] = g = CreateGadget(INTEGER_KIND,g,&ng, 
  1317.     STRINGA_Justification, GACT_STRINGCENTER, TAG_DONE)))
  1318.       return 8;
  1319.     ++ng.ng_GadgetID;
  1320.     ng.ng_TopEdge += ng.ng_Height + SEPARATE_SAME;
  1321.   }
  1322.  
  1323.   ng.ng_GadgetText = *txt;
  1324.  
  1325.   if(!(gadgdata[7] = g = CreateGadget(CYCLE_KIND,g,&ng, GTCY_Labels,
  1326.   text + TEXT_START_SLIDER, TAG_DONE)))
  1327.       return 9;
  1328.  
  1329.   ++ng.ng_GadgetID;
  1330.   ng.ng_TopEdge += ng.ng_Height + SEPARATE_DIFF;
  1331.   txt = text + GADG_Use_XFD;
  1332.   ng.ng_LeftEdge = j;
  1333.  
  1334.   for(i = k = 0; i < 3; ++i)
  1335.   {
  1336.     ng.ng_Width = 50 + TextLength(&Scr->RastPort, txt[i], SDI_strlen(txt[i]));
  1337.     if(ng.ng_Width > k)
  1338.       k = ng.ng_Width;
  1339.   }
  1340.  
  1341.   ng.ng_GadgetText = txt[3];
  1342.   ng.ng_LeftEdge += k + ng.ng_Height;
  1343.   if((ng.ng_Width = 7 + TextLength(&Scr->RastPort, txt[3],
  1344.   SDI_strlen(txt[3]))) < Scr->RastPort.TxWidth << 3)
  1345.     ng.ng_Width = Scr->RastPort.TxWidth << 3;
  1346.   ng.ng_Flags = PLACETEXT_BELOW;
  1347.   if(!(gadgdata[8] = g = CreateGadget(INTEGER_KIND,g,&ng, GTIN_MaxChars, 5, STRINGA_Justification,
  1348.   GACT_STRINGCENTER, TAG_DONE)))
  1349.       return 10;
  1350.   ++ng.ng_GadgetID;
  1351.   ng.ng_LeftEdge -= k + ng.ng_Height;
  1352.   ng.ng_Width = ng.ng_Height;
  1353.   ng.ng_Flags = PLACETEXT_RIGHT;
  1354.  
  1355.   for(i = 0; i < 3; ++i)
  1356.   {
  1357.     ng.ng_GadgetText = *(txt++);
  1358.     if(!(gadgdata[9+i] = g = CreateGadgetA(CHECKBOX_KIND,g,&ng,0)))
  1359.       return 11;
  1360.     ++ng.ng_GadgetID;
  1361.     ng.ng_TopEdge += ng.ng_Height;
  1362.   }
  1363.  
  1364.   if(winheight < ng.ng_TopEdge + 5)
  1365.     winheight = ng.ng_TopEdge + SEPARATE_DIFF;
  1366.  
  1367.   ng.ng_TopEdge = winheight;
  1368.   ng.ng_LeftEdge = Scr->WBorLeft + SEPARATE_BORD;
  1369.   ng.ng_Flags = PLACETEXT_IN;
  1370.   txt = text + GADG_Save;
  1371.  
  1372.   ng.ng_Width = 0;
  1373.   for(i = 0; i < 3; ++i)
  1374.   {
  1375.     k = 7 + TextLength(&Scr->RastPort, txt[i], SDI_strlen(txt[i]));
  1376.     if(k >ng.ng_Width)
  1377.       ng.ng_Width = k;
  1378.   }
  1379.   k = (winwidth - SEPARATE_BORD - 3*ng.ng_Width)/6;
  1380.   ng.ng_LeftEdge += k;
  1381.  
  1382.   for(i = 0; i < 3; ++i)
  1383.   {
  1384.     ng.ng_GadgetText = *(txt++);
  1385.     if(!(g = CreateGadgetA(BUTTON_KIND, g, &ng, 0)))
  1386.       return 12;
  1387.     ++ng.ng_GadgetID;
  1388.     ng.ng_LeftEdge += ng.ng_Width + (k<<1);
  1389.   }  
  1390.  
  1391.   winwidth += Scr->WBorRight + SEPARATE_BORD;
  1392.   winheight += Scr->WBorBottom + ng.ng_Height + SEPARATE_BORD;
  1393.  
  1394.   if(winwidth > Scr->Width || winheight > Scr->Height)
  1395.   {
  1396.     PrintError(text[TEXT_NO_WINDOW],0);
  1397.     return 20;
  1398.   }
  1399.  
  1400.   if(!(menus = CreateMenusA(NewMenus, 0)))
  1401.     return 21;
  1402.  
  1403.   LayoutMenus(menus, VisualInfo, GTMN_NewLookMenus, TRUE, TAG_DONE);
  1404.  
  1405.   if(!(window = OpenWindowTags(0,
  1406.     WA_Top,        Scr->BarHeight + 1,
  1407.     WA_Width,    winwidth,
  1408.     WA_Height,    winheight,
  1409.     WA_IDCMP,    IDCMP_GADGETUP|IDCMP_MENUPICK|IDCMP_GADGETDOWN|
  1410.             IDCMP_MOUSEMOVE|IDCMP_INTUITICKS|IDCMP_MOUSEBUTTONS,
  1411.     WA_Flags,    WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SMART_REFRESH,
  1412.     WA_Gadgets,    gadgList,
  1413.     WA_Title,    text[TEXT_WINDOW_TITLE],
  1414.     WA_AutoAdjust,    TRUE,
  1415.         WA_Activate,    TRUE,
  1416.     WA_NewLookMenus,TRUE,
  1417.     WA_PubScreen,    Scr,
  1418.     TAG_DONE)))
  1419.     return 22;
  1420.  
  1421.   ResetListView(0, &maindata);
  1422.   SetMainData();
  1423.   SetMenuStrip(window, menus);
  1424.   GT_RefreshWindow(window,0);
  1425.   ScreenToFront(Scr);
  1426.  
  1427.   return 0;
  1428. }
  1429.  
  1430. /* --------------------------- list functions -------------------------- */
  1431.  
  1432. void NewPackerList(struct ListData *ld)
  1433. {
  1434.   if(ld->ld_entries)
  1435.     FreePackerList(ld);
  1436.   TimeOut = DEF_TIMEOUT; XPKM_Flags = DEF_XPKM_FLAGS;
  1437.   if(!NewPackerNode(&maindata, text[TEXT_ENTRY_DEFAULT], 0, 0))
  1438.     End(RETURN_FAIL);
  1439.   maindata.ld_curNode->pn_Cycle = DEF_CYCLE;
  1440. }
  1441.  
  1442. void FreePackerList(struct ListData *li)
  1443. {
  1444.   struct Node *n;
  1445.   while((n = RemHead(&li->ld_List)))
  1446.     FreeMem(n, sizeof(struct PackerNode));
  1447.   li->ld_curNumber = li->ld_entries = 0;
  1448.   li->ld_curNode = 0;
  1449. }
  1450.  
  1451. struct Node *FindNode(struct List *li, ULONG num)
  1452. {
  1453.   struct Node *n = li->lh_Head;
  1454.  
  1455.   ++num;
  1456.   if(n == (struct Node *) li)
  1457.     return 0;
  1458.   while(--num)
  1459.   {
  1460.     if(n == li->lh_TailPred)
  1461.       return 0;
  1462.     n = n->ln_Succ;
  1463.   }
  1464.   return n;
  1465. }
  1466.  
  1467. struct PackerNode *NewPackerNode(struct ListData *li, STRPTR name,
  1468. struct PackerNode *pref, ULONG mode)
  1469. {
  1470.   struct PackerNode *n;
  1471.   ULONG i;
  1472.  
  1473.   if(!(n = (struct PackerNode *) AllocMem(sizeof(struct PackerNode), MEMF_ANY|MEMF_CLEAR)))
  1474.     return 0;
  1475.  
  1476.   if(pref)
  1477.     CopyMem((STRPTR) pref + sizeof(struct Node), (STRPTR) n +
  1478.     sizeof(struct Node), sizeof(struct PackerNode) - sizeof(struct Node));
  1479.  
  1480.   n->pn_Node.ln_Name = n->pn_TypeName;
  1481.   n->pn_Node.ln_Type = mode ? PACKER_NODE : DEFAULT_NODE;
  1482.  
  1483.   if((i = SDI_strlen(name) + 1) > TypeSIZE)
  1484.     i = TypeSIZE;
  1485.   CopyMem(name, &n->pn_TypeName, i);
  1486.  
  1487.   if(li)
  1488.   {
  1489.     struct Node *p;
  1490.     if((p = FindNode(&li->ld_List, mode)))
  1491.     {
  1492.       Insert(&li->ld_List, (struct Node *) n, p);
  1493.       li->ld_curNumber = mode + 1;
  1494.     }
  1495.     else
  1496.     {
  1497.       AddTail(&li->ld_List, (struct Node *) n);
  1498.       li->ld_curNumber = li->ld_entries;
  1499.     }
  1500.     li->ld_curNode = n;
  1501.     ++li->ld_entries;
  1502.   }
  1503.  
  1504.   return (struct PackerNode *) n;
  1505. }
  1506.  
  1507. /* ---------------------- the cleanup stuff ---------------------------- */
  1508.  
  1509. void end(void)
  1510. {
  1511.   if(diskobject)    FreeDiskObject(diskobject);
  1512.   if(window)
  1513.   {
  1514.     ClearMenuStrip(window);
  1515.     CloseWindow(window);
  1516.   }
  1517.   if(menus)        FreeMenus(menus);
  1518.   if(gadgList)        FreeGadgets(gadgList);
  1519.   if(VisualInfo)    FreeVisualInfo(VisualInfo);
  1520.   if(Scr)        UnlockPubScreen(0, Scr);
  1521.   if(GfxBase)        CloseLibrary((struct Library *) GfxBase);
  1522.   if(UtilityBase)    CloseLibrary(UtilityBase);
  1523.   if(GadToolsBase)    CloseLibrary(GadToolsBase);
  1524.   if(IntuitionBase)    CloseLibrary((struct Library *) IntuitionBase);
  1525.   if(IconBase)        CloseLibrary(IconBase);
  1526.   if(rda)        FreeArgs(rda);
  1527.   FreePackerList(&maindata);
  1528.   SDI_FreeLocale(&locdat);
  1529.   if(lock)        CurrentDir(lock);
  1530. }
  1531.  
  1532.